package com.atguigu.gmall.web.all.service.impl;

import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.feign.cart.CartFeignClient;
import com.atguigu.gmall.feign.product.SkuInfoFeignClient;
import com.atguigu.gmall.feign.user.UserFeignClient;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.web.all.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lsj
 * @create 2021-08-27 16:12
 */
@Service
public class OrderServiceImpl implements OrderService {


    @Autowired
    CartFeignClient cartFeignClient;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    SkuInfoFeignClient skuInfoFeignClient;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Qualifier("corePool")
    @Autowired
    ThreadPoolExecutor executor;


    @Override
    public Map<String, Object> getOrderConfirmInfo(String userId) {
        System.out.println("service主线程："+Thread.currentThread().getId());
        //从controller---service的主线程的request信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        Map<String,Object> map = new HashMap<>();

        //多线程要操作，使用AtomicInteger 防止并发。必须不可变类
        final BigDecimal[] totalAmount = {new BigDecimal("0.0")};
        final AtomicInteger[] totalNum = {new AtomicInteger(0)};
        //1、TODO  远程查询购物车服务，获取到购物车选中的所有商品列表
        CompletableFuture<List<CartInfo>> listCompletableFuture = CompletableFuture.supplyAsync(() -> {
            //每个人 调用了feign拦截器。

            System.out.println("CartInfo线程："+Thread.currentThread().getId());
            //自己异步线程把老请求内容放入，解决feign异步请求丢失请求头信息问题
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<CartInfo> detailArrayList = cartFeignClient.cartInfoListCheck();
            return detailArrayList;
        }, executor);
        //2、TODO 计算总价
        CompletableFuture<List<CartInfo>> priceAndNumFuture = listCompletableFuture.whenCompleteAsync((result, execption) -> {

            System.out.println("计算价格线程："+Thread.currentThread().getId());
            //自己异步线程把老请求内容放入
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<CartInfo> infos = new ArrayList<>();
            for (CartInfo cartInfo : result) {
                //总价 = 数量* 单价
//                totalNum += cartInfo.getSkuNum();
                Integer skuNum = cartInfo.getSkuNum();
                totalNum[0].addAndGet(skuNum); //叠加数量
                //3、 TODO 查询到最新的价格
                BigDecimal skuPrice = skuInfoFeignClient.getSkuPrice(cartInfo.getSkuId());
                cartInfo.setOrderPrice(skuPrice);
                BigDecimal multiply = skuPrice.multiply(new BigDecimal(skuNum.toString()));
                totalAmount[0] = totalAmount[0].add(multiply);
                infos.add(cartInfo);
            }

            map.put("detailArrayList",infos);
            map.put("totalNum",totalNum[0]);
            map.put("totalAmount",totalAmount[0]);
        }, executor);


        //3、TODO 远程查询用户的所有收货地址列表
        CompletableFuture<List<UserAddress>> addressFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println("地址线程："+Thread.currentThread().getId());
            //自己异步线程把老请求内容放入
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<UserAddress> address = userFeignClient.getCurrentUserAddress();
            map.put("userAddressList",address);
            return address;
        }, executor);


        //4、TODO 页面需要tradeNo，页面用来做防重复提交'
        CompletableFuture<Void> tokenFuture = CompletableFuture.runAsync(() -> {
            //后台生成的防重复令牌
            System.out.println("令牌线程："+Thread.currentThread().getId());
            String token = UUID.randomUUID().toString().replace("-", "");
            redisTemplate.opsForValue().set(RedisConst.USER_UNREPEAT_TOKEN + userId, token, RedisConst.USER_UNREPEAT_TOKEN_TTL, TimeUnit.SECONDS);
            map.put("tradeNo", token);
        }, executor);

        CompletableFuture
                .allOf(listCompletableFuture, priceAndNumFuture, addressFuture, tokenFuture)
                .join();  //所有都完成

        System.out.println("service主线程结束："+Thread.currentThread().getId());
        return map;
    }
}
